import { listen, UnlistenFn } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/core';
import { useWorkspaceStore } from '../stores/workspace';
import { workspaceIndexer } from './WorkspaceIndexer';

class WorkspaceServiceImpl {
  private static _instance: WorkspaceServiceImpl | null = null;
  static get instance(): WorkspaceServiceImpl {
    if (!this._instance) this._instance = new WorkspaceServiceImpl();
    return this._instance;
  }

  private fileWatcherUnlisten: UnlistenFn | null = null;
  private started = false;
  // debounce timer id for refresh
  private refreshTimer: any = null;
  // currently watched path (for idempotency)
  private currentPath: string = '';
  // generation token to avoid races between start/stop/setRoot
  private watchGen = 0;
  // 索引刷新防抖定时器
  private indexRefreshTimer: any = null;

  // 初始化：从设置恢复 + 启动监听（如果有 root）
  async start() {
    if (this.started) return;
    this.started = true;
    const store = useWorkspaceStore();
    try {
      await store.loadWorkspaceFromSettings();
    } catch {}
    // 使用 store 属性（Pinia 在 store 实例上会解包 ref）
    const root = String(store.workspaceRoot || '');
    if (root) {
      const gen = ++this.watchGen;
      await this.startWatching(root, gen);
    }
  }

  async stop() {
    await this.stopWatching();
    // 安全兜底：确保后端无残留 watcher
    try { await invoke('stop_all_watching'); } catch {}
    this.started = false;
  }

  async setRoot(path: string) {
    const store = useWorkspaceStore();
    // 停止之前的监听（并增加一代，取消并发中的 startWatching）
    await this.stopWatching();
    await store.setWorkspaceRoot(path);
    // 开始新的监听（如果有 path）
    const root = String(store.workspaceRoot || '');
    if (root) {
      const gen = ++this.watchGen;
      await this.startWatching(root, gen);
    }
  }

  private async startWatching(path: string, gen: number) {
    if (!path) return;
    // 已在同一路径上监听且监听仍然有效 -> 跳过
    if (this.currentPath === path && this.fileWatcherUnlisten) {
      return;
    }
    const store = useWorkspaceStore();
    try {
      await invoke('start_watching_directory', { path });
      // 如果在等待期间发生了代际变更，取消后续绑定
      if (gen !== this.watchGen) return;

      // 清理旧的事件监听
      if (this.fileWatcherUnlisten) {
        try { this.fileWatcherUnlisten(); } catch {}
        this.fileWatcherUnlisten = null;
      }
      this.currentPath = path;
      this.fileWatcherUnlisten = await listen('file-system-change', (evt: any) => {
        // 将 payload 透传为浏览器自定义事件，供增量刷新调用方消费
        try {
          const payload = evt?.payload;
          if (payload && typeof window !== 'undefined' && window?.dispatchEvent) {
            try { window.dispatchEvent(new CustomEvent('fs-change', { detail: payload })); } catch {}
          }
          
          // 处理索引更新
          this.handleFileSystemChange(payload);
        } catch {}
        
        // 防抖刷新：减少频繁文件事件导致的 UI 过度刷新（兜底）
        if (this.refreshTimer) {
          clearTimeout(this.refreshTimer);
          this.refreshTimer = null;
        }
        this.refreshTimer = setTimeout(() => {
          try { store.refreshWorkspace(); } catch {}
          this.refreshTimer = null;
        }, 200);
      });
      console.log('WorkspaceService: started watching', path);
    } catch (error) {
      console.error('WorkspaceService: failed to start watching', error);
    }
  }

  private async stopWatching() {
    const store = useWorkspaceStore();
    try {
      // bump generation，取消并发中的 startWatching
      this.watchGen++;
      // 清理刷新防抖
      if (this.refreshTimer) {
        clearTimeout(this.refreshTimer);
        this.refreshTimer = null;
      }
      // 清理索引刷新防抖
      if (this.indexRefreshTimer) {
        clearTimeout(this.indexRefreshTimer);
        this.indexRefreshTimer = null;
      }
      const path = String(store.workspaceRoot || '');
      if (path) {
        await invoke('stop_watching_directory', { path });
      }
      if (this.fileWatcherUnlisten) {
        try { this.fileWatcherUnlisten(); } catch {}
        this.fileWatcherUnlisten = null;
      }
      this.currentPath = '';
      console.log('WorkspaceService: stopped');
    } catch (error) {
      console.error('WorkspaceService: failed to stop', error);
    }
  }
  
  // 处理文件系统变化事件，更新索引
  private handleFileSystemChange(payload: any) {
    if (!payload) return;
    
    const eventType = String(payload.event_type || '');
    const path = String(payload.path || '');
    const oldPath = payload.old_path ? String(payload.old_path) : undefined;
    
    if (!eventType || !path) return;
    
    // 防抖更新索引，避免频繁的文件变化导致过度刷新
    if (this.indexRefreshTimer) {
      clearTimeout(this.indexRefreshTimer);
    }
    
    this.indexRefreshTimer = setTimeout(() => {
      this.updateIndexForFileChange(eventType, path, oldPath);
      this.indexRefreshTimer = null;
    }, 300); // 300ms 防抖
  }
  
  // 根据文件变化类型更新索引
  private async updateIndexForFileChange(eventType: string, path: string, oldPath?: string) {
    try {
      const store = useWorkspaceStore();
      
      // 获取受影响的父目录
      const getParentDir = (filePath: string) => {
        const normalized = filePath.replace(/\\/g, '/');
        const lastSlash = normalized.lastIndexOf('/');
        return lastSlash > 0 ? normalized.substring(0, lastSlash) : null;
      };
      
      const parentDir = getParentDir(path);
      const oldParentDir = oldPath ? getParentDir(oldPath) : null;
      
      switch (eventType.toLowerCase()) {
        case 'create':
        case 'delete':
          // 文件或目录的创建/删除，更新父目录索引
          if (parentDir && store.isDirectoryIndexed(parentDir)) {
            await store.refreshDirectoryIndex(parentDir);
            console.log(`Updated index for directory: ${parentDir} (${eventType})`);
          }
          break;
          
        case 'rename':
        case 'modify':
          // 重命名或修改，更新相关目录索引
          if (parentDir && store.isDirectoryIndexed(parentDir)) {
            await store.refreshDirectoryIndex(parentDir);
            console.log(`Updated index for directory: ${parentDir} (${eventType})`);
          }
          if (oldParentDir && oldParentDir !== parentDir && store.isDirectoryIndexed(oldParentDir)) {
            await store.refreshDirectoryIndex(oldParentDir);
            console.log(`Updated index for old directory: ${oldParentDir} (${eventType})`);
          }
          break;
          
        default:
          console.debug(`Unhandled file system event: ${eventType}`);
      }
    } catch (error) {
      console.warn('Failed to update index for file change:', error);
    }
  }
}

export const WorkspaceService = WorkspaceServiceImpl.instance;
